(function ($) {
	'use strict';
	
	// Create the mosaic namespace if it doesn't exist.
	if (!('mosaic' in window)) window.mosaic = {};
	
	// Custom lifecycle hooks with constant names.
	mosaic.hooks = {
		AFTER_DOCUMENT_LOADED: 'afterDocumentLoaded',
		AFTER_TEMPLATES_LOADED: 'afterTemplatesLoaded',
		JOIN_DISCUSSION: 'joinDiscussion',
		VIEW_DISCUSSION: 'viewDiscussion'
	};
	
	// Trigger the afterDocumentLoaded hook when the document loads.
	$(document).ready(function () { $(mosaic).trigger(mosaic.hooks.AFTER_DOCUMENT_LOADED); });

	// Set of templates to load and use...
	mosaic.templates =	{
		NEW_DISCUSSION_FORM_TMPL: '#join-discussion-form-tmpl',
		DISCUSSION_TMPL: '#discussion-tmpl',
		POST_TMPL: '#post-tmpl'
	};
	
	var templateUrls = [
		'/templates/join-discussion-form.tmpl.html',
		'/templates/discussion.tmpl.html'
	];
	
	// After document load, try to load the templates.
	$(mosaic).bind(mosaic.hooks.AFTER_DOCUMENT_LOADED, function loadTemplates() {
		var templatesLoaded = 0;
		function processTemplate (templateHtml) {
			templatesLoaded += 1;
			$('body').append(templateHtml);
			if (templatesLoaded === templateUrls.length) $(mosaic).trigger(mosaic.hooks.AFTER_TEMPLATES_LOADED);
		};
		$(templateUrls).each(function loadTemplate (index, url) {
			$.get(url).success(processTemplate);
		});
	});

	// After templates load, display the new discussion form.
	$(mosaic).bind(mosaic.hooks.AFTER_TEMPLATES_LOADED, function () {
		$(mosaic.templates.NEW_DISCUSSION_FORM_TMPL).tmpl().appendTo('#content');
		var processing = false;
		function joinDiscussion() {
			if (processing) return;
			processing = true;
			$('#join-discussion-create-button').attr('disabled', 'disabled');
			$('#join-discussion-create-button').removeClass('enabled').addClass('disabled');
			$.post('/api/discussions/join/', { name: $('#join-discussion-name').val() })
				.success(function(response) {
					$(mosaic).trigger(mosaic.hooks.VIEW_DISCUSSION, response.discussion);
				})
				.error(function(response) {
					alert('Error! ' + response.responseText);
					$('#join-discussion-create-button').removeAttr('disabled');
					$('#join-discussion-create-button').removeClass('disabled').addClass('enabled');
				}).complete(function () {
					processing = false;
				});
		}
		$('#join-discussion-create-button').click(joinDiscussion);
		$('#join-discussion-name').bind('keyup', function(event) { if (event.keyCode === 13) joinDiscussion(); });
	});
	
	// Bind to create the desired discussion and alert its ID (or failure).
	$(mosaic).bind(mosaic.hooks.JOIN_DISCUSSION, function (event, name) {
	});
	
	// Bind to show the discussion when it's joined.
	$(mosaic).bind(mosaic.hooks.VIEW_DISCUSSION, function (event, discussion) {
		var postsUrl = '/api/discussions/' + discussion.id + '/posts';
		var processing = false;

		$('#content').empty();
		$(mosaic.templates.DISCUSSION_TMPL).tmpl(discussion).appendTo('#content');
		
		function submitNewPost() {
			if (processing) return;
			processing = true;
			$('#submit-post-button').attr('disabled', 'disabled');
			$('#submit-post-button').removeClass('enabled').addClass('disabled');
			$.post(postsUrl, { body: $('#new-post-body').val() })
				.success(function (response) {
					var postsWindow = $('#posts');
					discussion.posts.push(response.post);
					var scrolledToBottom = (postsWindow.scrollTop() === (postsWindow.prop('scrollHeight') - postsWindow.height()));
					$(mosaic.templates.POST_TMPL).tmpl(response.post).appendTo(postsWindow);
					if (scrolledToBottom) postsWindow.scrollTop(postsWindow.prop('scrollHeight'));
				}).complete(function () {
					$('#new-post-body').val('');
					$('#submit-post-button').removeAttr('disabled');
					$('#submit-post-button').removeClass('disabled').addClass('enabled');
					processing = false;
				});
		};
		
		$('#new-post-body').bind('keyup', function(event) { if (event.ctrlKey && event.keyCode === 13) submitNewPost(); });
		$('#submit-post-button').click(submitNewPost);
	});
	
})(jQuery);